package own.stu.jobgib.playown.fsm.squirrel;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.squirrelframework.foundation.fsm.StateMachineBuilderFactory;
import org.squirrelframework.foundation.fsm.UntypedStateMachineBuilder;
import org.squirrelframework.foundation.fsm.annotation.State;
import org.squirrelframework.foundation.fsm.annotation.StateMachineParameters;
import org.squirrelframework.foundation.fsm.annotation.States;
import org.squirrelframework.foundation.fsm.impl.AbstractUntypedStateMachine;

import static own.stu.jobgib.playown.fsm.squirrel.HelloStartSample.OrderChangedEnum.ORDER_DELIVERY;
import static own.stu.jobgib.playown.fsm.squirrel.HelloStartSample.OrderChangedEnum.TO_DELIVERY;
import static own.stu.jobgib.playown.fsm.squirrel.HelloStartSample.OrderState.*;

@States({
        @State(name = "PAYED"),
        @State(name = "DELIVERY"),
        @State(name = "SIGNED")
})
@StateMachineParameters(
        stateType = HelloStartSample.OrderState.class,
        eventType = HelloStartSample.OrderChangedEnum.class,
        contextType = Object.class
)
@Slf4j
public class HelloStartSample extends AbstractUntypedStateMachine {

    public enum OrderState {
        PAYED,
        DELIVERY,
        SIGNED
    }

    @Getter
    @AllArgsConstructor
    enum OrderChangedEnum {
        TO_DELIVERY(PAYED, DELIVERY, "findDeliver"),
        ORDER_DELIVERY(DELIVERY, SIGNED, "delivering"),

        ;

        private OrderState fromState;
        private OrderState toState;
        private String operate;
    }

    public void findDeliver(OrderState from, OrderState to, OrderChangedEnum event, Object context) {
        log.info("order: {} dispatcher, cur state is {} ", context, to);
    }

    public void delivering(OrderState from, OrderState to, OrderChangedEnum event, Object context) {
        try {
            log.info("order: {} delivering, cur state is {} ", context, to);
            int i = 10 / 0;
        } catch (Exception e) {
            log.error("delivering error: ", e.getMessage());
            ex.set(e);
        }
    }

    ThreadLocal<Exception> ex = ThreadLocal.withInitial(() -> null);

    public static void main(String[] args) {
        UntypedStateMachineBuilder machineBuilder = StateMachineBuilderFactory.create(HelloStartSample.class);
        for (OrderChangedEnum value : OrderChangedEnum.values()) {
            machineBuilder.externalTransition()
                    .from(value.fromState).to(value.toState).on(value)
                    .callMethod(value.getOperate());
        }

        HelloStartSample fsm = machineBuilder.newUntypedStateMachine(PAYED);
        fsm.fire(TO_DELIVERY, "O_0001");
        fsm.fire(ORDER_DELIVERY, "O_0001");
        if (fsm.ex.get() != null) {
            log.error("可以转为自定义的异常 ：", fsm.ex.get());
        }

        /*
        no error : cur state : SIGNED
         */
        log.info("cur state : {}", fsm.getCurrentState());
        fsm.terminate();
    }
}




